package com.csaba.connector.otp;

import java.io.StringReader;
import java.util.Arrays;
import java.util.Calendar;
import java.util.logging.Logger;

import org.apache.commons.httpclient.NameValuePair;

import com.csaba.connector.ServiceException;
import com.csaba.connector.model.HistoryItem;
import com.csaba.connector.model.Session;
import com.csaba.connector.otp.model.OTPBank;
import com.csaba.connector.otp.model.OTPRequestFactory;
import com.csaba.connector.otp.model.OTPSession;
import com.csaba.connector.otp.parser.AccountBalanceParser;
import com.csaba.connector.otp.parser.AccountHistoryParser;
import com.csaba.connector.service.AbstractAccountHistoryService;
import com.csaba.util.LoggerHelper;

public class OTPAccountHistoryService extends AbstractAccountHistoryService
{

	public static final int HISTORY_TIME_LIMIT = 92;

	private final static Logger logger = LoggerHelper.getDefaultLogger();

	private final static String ACCOUNT_SELECTION = "account.selection";

	@Override
	public void execute( final Session session ) throws ServiceException
	{
		if ( !( session instanceof OTPSession ) )
			throw new ServiceException("Incompatible session " + OTPBank.class + " != " + session.getClass().getName());

		if ( account == null || !OTPBank.getInstance().equals(account.getBank()) || from == null || to == null )
			throw new ServiceException("Service is not initialized yet correctly.");

		//time range is limited to 3 month (92 days)... 
		final Calendar timeLimit = Calendar.getInstance();
		timeLimit.add(Calendar.DATE, -HISTORY_TIME_LIMIT);

		if ( timeLimit.getTime().after(from) )
		{
			//TODO account statement function can be used in this case to get more than 3 month accoun history.
			throw new ServiceException("Account history is available only for the last 3 month in the OTP.");
		}

		final OTPSession otp = (OTPSession) session;

		//select account if not yet selected
		boolean needToSelect = true;
		try
		{
			final String accountSelect = (String) session.getRemoteProperty(ACCOUNT_SELECTION);
			needToSelect = !accountSelect.equals(account.getRemoteProperty(AccountBalanceParser.ACCOUNT_INDEX));
		}
		catch ( final Exception ex )
		{
			logger.finer("Remote property is missing: " + ex);
		}

		if ( needToSelect )
		{
			final String accountSelectResult = otp.doGet(OTPRequestFactory.HOMEBANK_REQUEST_URL_BASE
					+ OTPRequestFactory.REQUEST_GET_ACCOUNT_LIST + "?szamlaSzamIndex="
					+ account.getRemoteProperty(AccountBalanceParser.ACCOUNT_INDEX));
			otp.debugFile("accountSelectResult", accountSelectResult);
			if ( AccountHistoryParser.isFailed(accountSelectResult) )
			{
				/* Errors: FIXME parse error
				 	<div class="hibak">
					<h3 class="hibacim">Hiba történt a művelet végrehajtása közben.</h3>

				 */
				throw new ServiceException("Error during downloading account history for OTP account: " + account);
			}

			otp.setRemoteProperty(ACCOUNT_SELECTION, account.getRemoteProperty(AccountBalanceParser.ACCOUNT_INDEX));
		}

		final Calendar from = Calendar.getInstance();
		final Calendar to = Calendar.getInstance();
		from.setTime(this.from);
		to.setTime(this.to);
		//post input request
		final NameValuePair[] inputData = new NameValuePair[] {// 
		new NameValuePair("muveletStatusz", "bevitel"),//
				new NameValuePair("kliensTranzakcioId", ""), //
				new NameValuePair("induloDatum.ev", String.valueOf(from.get(Calendar.YEAR))),//
				new NameValuePair("induloDatum.honap", String.valueOf(from.get(Calendar.MONTH) + 1)),//
				new NameValuePair("induloDatum.nap", String.valueOf(from.get(Calendar.DATE))),//
				new NameValuePair("zaroDatum.ev", String.valueOf(to.get(Calendar.YEAR))),//
				new NameValuePair("zaroDatum.honap", String.valueOf(to.get(Calendar.MONTH) + 1)),//
				new NameValuePair("zaroDatum.nap", String.valueOf(to.get(Calendar.DATE))),//
				new NameValuePair("forgalomFeltetel", "0"),//both credit and debit
				new NameValuePair("szamlaszamFeltetel", ""),//
				new NameValuePair("formButtons(elkuld).x", String.valueOf((int) ( Math.random() * 30 ))),//
				new NameValuePair("formButtons(elkuld).y", String.valueOf((int) ( Math.random() * 30 ))), };
		logger.fine("History params: " + Arrays.toString(inputData));

		final String requestResult = otp.doPost(OTPRequestFactory.HOMEBANK_REQUEST_URL_BASE
				+ OTPRequestFactory.REQUEST_GET_ACCOUNT_HISTORY, inputData);
		otp.debugFile("accountHistoryRequestResult", requestResult);

		if ( AccountHistoryParser.isFailed(requestResult) )
		{
			/* Errors: FIXME parse error
			 	<div class="hibak">
				<h3 class="hibacim">Hiba történt a művelet végrehajtása közben.</h3>

			 */
			throw new ServiceException("Error during downloading account history for OTP account: " + account);
		}

		//poll response
		final NameValuePair[] pollData = new NameValuePair[] {// 
		new NameValuePair("muveletStatusz", "varakozas"),//
				new NameValuePair("kliensTranzakcioId", String.valueOf(otp.getOperationCounter())), };

		int pollCount = 0;
		String finalResult = null;
		for ( ; finalResult == null && pollCount < TransactionPolling.POLL_LIMIT; pollCount++ )
		{
			try
			{
				Thread.sleep(TransactionPolling.POLL_PERIOD);
			}
			catch ( final InterruptedException ex )
			{
				logger.finest("Sleep was interrupted.");
			}

			final String pollResult = otp.doPost(OTPRequestFactory.HOMEBANK_REQUEST_URL_BASE
					+ OTPRequestFactory.REQUEST_GET_ACCOUNT_HISTORY, pollData);
			otp.debugFile("accountHistoryPollResult", pollResult);

			if ( !pollResult.contains("varakozas_animacio") )
			{
				finalResult = pollResult;
			}
		}

		if ( finalResult == null )
		{
			throw new ServiceException("Unable to get account history within the timeout period ("
					+ ( TransactionPolling.POLL_LIMIT * TransactionPolling.POLL_PERIOD / 1000 ) + ") for account "
					+ account);
		}

		//parse result
		if ( AccountHistoryParser.isParsable(finalResult) )
		{
			try
			{
				historyItems = AccountHistoryParser.parseAccountHistoryList(new StringReader(finalResult), account);
			}
			catch ( final Exception e )
			{
				throw new ServiceException("Error during processing account history.", e);
			}
		}
		else
		{
			//check if there is any error
			if ( AccountHistoryParser.isFailed(finalResult) )
			{
				/* Errors: FIXME parse error
				<div class="hibak">
				<h3 class="hibacim">Hiba történt a művelet végrehajtása közben.</h3>

				*/
				throw new ServiceException("Unable to download a valid account history for account: " + account);
			}
			else
			{
				historyItems = new HistoryItem[0];
			}
		}

	}
	//account select: https%3A//www.otpbankdirekt.hu/homebank/do/bankszamla/bankszamlaMuvelet%3Bjsessionid%3DL8qJsCZcrSJ2m0gQf3PysyDjGNZ1gdTK9TgjqDZhLTdqP8jJYRZV%211577071256%21NONE%3FszamlaSzamIndex%3D0

	//input URI: https%3A//www.otpbankdirekt.hu/homebank/do/bankszamla/szamlatortenet%3Bjsessionid%3DL8ypbSGy9P3rz7v8GVrhhtLhsRLBhncQLLjXJQRtNtCg4Gx5LZpS%211580759978%211577071256

	//request: https%3A//www.otpbankdirekt.hu/homebank/do/bankszamla/szamlatortenet%3Bjsessionid%3DL8ypbSGy9P3rz7v8GVrhhtLhsRLBhncQLLjXJQRtNtCg4Gx5LZpS%211580759978%211577071256
	/*
	<tdPostElements>
		<tdPostElement name="muveletStatusz">bevitel</tdPostElement>
		<tdPostElement name="kliensTranzakcioId"></tdPostElement>
		<tdPostElement name="induloDatum.ev">2008</tdPostElement>
		<tdPostElement name="induloDatum.honap">6</tdPostElement>
		<tdPostElement name="induloDatum.nap">1</tdPostElement>
		<tdPostElement name="zaroDatum.ev">2008</tdPostElement>
		<tdPostElement name="zaroDatum.honap">7</tdPostElement>
		<tdPostElement name="zaroDatum.nap">15</tdPostElement>
		<tdPostElement name="forgalomFeltetel">0</tdPostElement> [2=credit, 1=debit, 0=both]
		<tdPostElement name="szamlaszamFeltetel"></tdPostElement> [partner accout filtering]
		<tdPostElement name="formButtons%28elkuld%29.x">30</tdPostElement>
		<tdPostElement name="formButtons%28elkuld%29.y">9</tdPostElement>
	</tdPostElements>

	 */

	//https%3A//www.otpbankdirekt.hu/homebank/do/bankszamla/szamlatortenet%3Bjsessionid%3DL8ypbSGy9P3rz7v8GVrhhtLhsRLBhncQLLjXJQRtNtCg4Gx5LZpS%211580759978%211577071256
	/*
	<tdPostElements>
		<tdPostElement name="kliensTranzakcioId">5</tdPostElement>
		<tdPostElement name="muveletStatusz">varakozas</tdPostElement>
	</tdPostElements>

	 */

}
